package com.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.filter.JwtFilter;
import com.shiro.authenticator.CustomModularRealmAuthenticator;
//import com.shiro.realm.AdminRealm;
import com.shiro.credentialsMatcher.JwtCredentialsMatcher;
import com.shiro.realm.AdminRealm;
import com.shiro.realm.CustomerRealm;
import com.shiro.realm.JwtRealm;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SessionStorageEvaluator;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.*;

/**
 * @author WxrStart
 * @create 2022-05-20 8:46
 */
@Configuration
public class ShiroConfig {

    //ShiroFilter过滤所有请求
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //给ShiroFilter配置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //自定义过滤器
        LinkedHashMap<String, Filter> filtsMap=new LinkedHashMap<String, Filter>();
        filtsMap.put("jwtFilter", jwtFilter());

        shiroFilterFactoryBean.setFilters(filtsMap);

        //添加shiro的内置过滤器
        /*
         * anon:无需认证就可以访问
         * authc:必须认证了才能让问
         * user: 必须拥有记住我功能才能用
         * perms:拥有对某个资源的权限才能访问、
         * role:拥有某个角色权限才能访问
         * */
        //配置系统受限资源
        //配置系统公共资源
        Map<String, String> map = new LinkedHashMap<>();
        //表示这个资源需要认证和授权
//        map.put("/", "anon"); // 可匿名访问
//        map.put("/filterError/{code}/{message}", "anon"); // 可匿名访问
//        map.put("/loginbyphone", "anon"); // 可匿名访问
//        map.put("/index", "anon"); // 可匿名访问
//        map.put("/captcha", "anon"); // 可匿名访问
//        map.put("/send_code", "anon"); // 可匿名访问
//        map.put("/regist", "anon"); // 可匿名访问
//        map.put("/loginbyemail", "anon"); // 可匿名访问
//        map.put("/css/**","anon");//静态资源不做拦截
//        map.put("/js/**","anon");//静态资源不做拦截
//        map.put("/img/**","anon");//静态资源不做拦截
//        map.put("/logo.ico","anon");//静态资源不做拦截
//        map.put("/admin/login", "anon"); // 管理员才能访问
//        map.put("/logout", "logout"); // 退出登录
//        map.put("/admin/index","roles[admin]");// 管理员才能访问
        map.put("/admin/index","jwtFilter"); // 管理员才能访问
        map.put("/seckill/**", "jwtFilter,authc"); // 需登录才能访问
        map.put("/orders/**", "jwtFilter,authc"); // 需登录才能访问
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        // 设置未授权跳转路径
        shiroFilterFactoryBean.setUnauthorizedUrl("http://localhost:8080/index");
        //设置未认证跳转路径
//        shiroFilterFactoryBean.setLoginUrl("/admin");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }

    //创建自定义Realm
    @Bean
    public CustomerRealm getRealmByUser() {
        CustomerRealm customerRealm = new CustomerRealm();
        //修改凭证匹配校验器
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        //设置加密算法为MD5
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        hashedCredentialsMatcher.setHashIterations(1024);
        customerRealm.setCredentialsMatcher(hashedCredentialsMatcher);
        return customerRealm;
    }

    //创建自定义Realm
    @Bean
    public Realm getRealmByAdmin() {
       AdminRealm adminReaml=new AdminRealm();
        //修改凭证匹配校验器
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        //设置加密算法为MD5
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        hashedCredentialsMatcher.setHashIterations(1024);

        adminReaml.setCredentialsMatcher(hashedCredentialsMatcher);
        return adminReaml;
    }



    //创建自定义Realm
    @Bean
    public JwtRealm getJwtRealm() {
        JwtRealm jwtRealm = new JwtRealm();
        // 设置加密算法
        CredentialsMatcher credentialsMatcher = new JwtCredentialsMatcher();
        // 设置加密次数
        jwtRealm.setCredentialsMatcher(credentialsMatcher);
        return jwtRealm;
    }


    //创建jwtFilter
    public JwtFilter jwtFilter() {
        return new JwtFilter();
    }


    /**
     * 安全管理器
     */
    @Bean
    public DefaultWebSecurityManager  securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关闭shiro的session（无状态的方式使用shiro）
        // 3.关闭shiro自带的session
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        subjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator());
        securityManager.setSubjectDAO(subjectDAO);

        //设置自定义realm认证器
        securityManager.setAuthenticator(modularRealmAuthenticator());
        // 注入session的管理
        securityManager.setSessionManager(sessionManager());

        List<Realm> realms = new ArrayList<>();
        //添加多个Realm
        realms.add(getRealmByUser());
        realms.add(getRealmByAdmin());
        realms.add(getJwtRealm());
        securityManager.setRealms(realms);
        return securityManager;
    }
    /**
     * 系统自带的Realm管理，主要针对多realm
     * */
    @Bean
    public ModularRealmAuthenticator modularRealmAuthenticator(){
        //自己重写的ModularRealmAuthenticator
        CustomModularRealmAuthenticator modularRealmAuthenticator = new CustomModularRealmAuthenticator();
        modularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
        return modularRealmAuthenticator;
    }

    @Bean
    public DefaultWebSessionManager sessionManager() {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        // 去掉shiro登录时url里的JSESSIONID
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        return sessionManager;
    }


    /**
     * 引入shiro支持thymeleaf
     * @return
     */
    @Bean
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }


    /**
     * 禁用session, 不保存用户登录状态。保证每次请求都重新认证
     */
    @Bean
    protected SessionStorageEvaluator sessionStorageEvaluator() {
        DefaultSessionStorageEvaluator sessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        sessionStorageEvaluator.setSessionStorageEnabled(false);
        return sessionStorageEvaluator;
    }


    /**
     * 交由 Spring 来自动地管理 Shiro-Bean 的生命周期
     */
    @Bean
    public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    /**
     * 为 Spring-Bean 开启对 Shiro 注解的支持
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator app = new DefaultAdvisorAutoProxyCreator();
        app.setProxyTargetClass(true);
        return app;

    }

}
